/****** version : 20051227-2147 ***********/

#define ADDR_TYPE_IPV4  AF_INET 
#define ADDR_TYPE_IPV6  AF_INET6 

struct ip_address{
     unsigned char  addrType;
     unsigned char  ipAddress[16];
     struct ip_address * next;
};

#define SRVC_TYPE_SOCKS4 0x01
#define SRVC_TYPE_SOCKS5 0x02
#define SRVC_TYPE_HTTP   0x04
#define SRVC_TYPE_SMS    0x08  // Short Message  


#define PROTOCOL_ICMP 1
#define PROTOCOL_TCP  6
#define PROTOCOL_UDP  17

#define SOCKS4_PORT  2080
#define SOCKS5_PORT  2081
#define HTTP_PORT    9080

struct service_item {
   int srvcType;
   int relayPort;
   int status;       // SRVC_STAT_DOWN(0) , or SRVC_STAT_UP(1)
   struct service_item *next; 
};

struct service {
	struct service_item *first;
	int number; //numberOfServices; 
};

#define MAX_USERNAME 32
#define MAX_METHODS  8 
#define MAX_SECRET   16 
#define MAX_NEIGHBORS 100

#define DEFAULT_PORT_CTRL 2006

struct node_item{
   int nodeID;
   char userName[MAX_USERNAME];  /* < 32 bytes*/
   unsigned char  addrType;

   in_addr_t  ipAddress; 
			// This address maybe a NATed ip, or  non-NATed but behind a firewall
			// When neighbor connected, it should  be replaced with its real ip 
   unsigned   int  controlPort;
    
   //X509  *selfSignedCertificate; 
   // the following fields are used only by self-node;
   //PrivateKey    *privateKey;

   unsigned int  authMethods[MAX_METHODS];
      
   int sourceNode;
   int status ;  // STATUS_XXXX  
   int underFirewall;

   char secret[MAX_SECRET];  //used for AuthMethod: PASS, CHAP
   //char peer_secret[MAX_SECRET];  //used for AuthMethod: PASS, CHAP
   // secret is used to login into the re
   //X509 *authorizedCertificate;//used for AuthMethod: X509 or PGP

   struct service  services ; 

   struct node_item *next;
};

struct node{
	struct node_item *first;
	int number;
};
#define STATUS_UNKNOWN 1
#define STATUS_AUTHED 2
#define STATUS_ACTIVE 3

struct route_item{
   unsigned char     netType ;  /*IPv4, IPv6, short message ,... */
   unsigned char     netAddress[16]; 
   unsigned char     prefix;    /* netmask*/
   unsigned char     hops;    /*  hops to the network */
   unsigned long     bandwidth;  	/*  bandwidth,  Kbps*/   			
   unsigned char     nextHop;
   //char   	     nextHop[MAX_USERNAME];		
   struct route_item * next;
};

struct route{
	struct route_item *first;
	int number;
};

struct access_list_item4{
   in_addr_t   netAddress;
   in_addr_t   mask;
   unsigned char     prefix;    
   unsigned char     action;    /* PERMIT, DENY, LOG */
   struct access_list_item4 * next;
};

#define ACTION_PERMIT 0x01
#define ACTION_DENY   0x02
#define ACTION_LOG    0x04

struct access_list4 {
    struct access_list_item4 *first;
    int number;
};

struct hash_item{
	unsigned long address;
	unsigned short port;
	int nextHop;
	time_t  time_update;	
	struct hash_item * next;
};
struct hash_index{
	short key;
	struct hash_item *list;
};

#define MAX_HASH  1024*10 
	

#define BANDWIDTH_ADSL        512
#define BANDWIDTH_ETHER10     10*1024
#define BANDWIDTH_ETHER100    100*1024
#define BANDWIDTH_ETHER1000   1000*1024


struct pdu_header{
   unsigned char version:8 ;// __attribute__((packed));
   unsigned char command  __attribute__((packed));			
};

typedef struct pdu_header PDU_HEADER;

#define VERSION_CTRL 1

#define  CMD_CERT_UPDATE	0x01  
#define  CMD_CERT_ACCEPT	0x02 
#define  CMD_CERT_REJECT	0x03

#define  CMD_CLIENT_HELLO	0x06      // C->S:(userName)
#define  CMD_SERVER_HELLO	0x07	  // S->C:(challenge)
#define  CMD_SERVER_NOUSER	0x08	  // No such user 
#define  CMD_SERVER_REJECT	0x09	  //  Reject 

#define  CMD_CLIENT_AUTH	0x09      // C->S:(response)
#define  CMD_SERVER_CONF	0x0a	  // S->C: (status)
#define  CMD_SERVER_ERROR	0x0b	  // S->C:  Authentication Failure 
   		
#define  CMD_SRVC_UPDATE         0x11    //17
#define  CMD_SRVC_ACCEPT      	 0x12    //18
#define  CMD_SRVC_REJECT    	 0x13    //19    
#define  CMD_SRVC_REVERSE      	 0x14    //20

#define  CMD_NODE_UPDATE        0x21    //33
#define  CMD_NODE_ACCEPT      	0x22    //34
#define  CMD_NODE_REJECT    	0x23    //35    

#define  CMD_NODE_REGISTER    		0x24    //36
#define  CMD_NODE_REGISTER_ACCEPT    	0x25   //37
#define  CMD_NODE_REGISTER_DENY    	0x26  //38
#define  CMD_NODE_REGISTER_USER_EXIST  	0x27 //39

		
#define  CMD_NBR_REQUEST        0x31   //49
#define  CMD_NBR_RESPONSE     	0x32
#define  CMD_NBR_REJECT  	0x33

#define  CMD_ROUTE_UPDATE       0x41    
#define  CMD_ROUTE_ACCEPT      	0x42   
#define  CMD_ROUTE_REJECT    	0x43  

// for administration 

#define  CMD_ADMIN      0x50

#define  ADMIN_NBR       0x60
#define  ADMIN_LIST      0x61
#define  ADMIN_ADD       0x62
#define  ADMIN_DEL       0x63
#define  ADMIN_UPDATE    0x64


#define  ADMIN_SRVC      0x70
#define  ADMIN_START     0x71
#define  ADMIN_STOP      0x72
#define  ADMIN_PAUSE     0x73

#define  ADMIN_ROUTE       0x80
#define  ADMIN_CACHE       0x90
#define  ADMIN_SESSION     0xA0

#define SRVC_STAT_START ADMIN_START  
#define SRVC_STAT_STOP  ADMIN_STOP  
#define SRVC_STAT_PAUSE ADMIN_PAUSE



#define  CMD_STAT_ERROR         0xFF


#define METHOD_NONE  1 
#define METHOD_PASS  2
#define METHOD_CHAP  3
#define METHOD_X509  4 
#define METHOD_PGP   5 
#define METHOD_ERROR 0xFF

#define PORT_REVERSE_BASE 20000


typedef struct {
    int num;
    const char *str;
} LOOKUP_ITEM;

extern int openSockets[MAX_NEIGHBORS];
extern int pointer;


#ifndef _TUNNET_C
extern  LOOKUP_ITEM service_name[];
extern  LOOKUP_ITEM address_type[];
extern  LOOKUP_ITEM network_type[];
extern  LOOKUP_ITEM auth_methods[];
#endif

int lookup_name(LOOKUP_ITEM * items, char *name);
int check_addressType(char *type_str);
unsigned short  hash_address(unsigned long dst_addr, unsigned short dst_port);
int service_insert(struct service * srvc, struct service_item* sp1);


int service_display(struct service *srvc);
int service_update_nbr(int nodeID, unsigned char sType, unsigned short rPort);
int service_delete(struct service *srvc);
int service_clean(struct service *srvc);

int neighbor_delete(struct node *np);
int neighbor_clean(struct node *np);
int neighbor_insert(struct node * np,struct node_item * sp1);
int neighbor_display(struct node *np);

struct node_item* neighbor_lookup_id(struct node *np, int nodeID);
struct node_item* neighbor_lookup_byName(struct node * np, char * userName);
struct node_item* neighbor_lookup_byIP(struct node * np, long ipAddress);

struct node_item* neighbor_update(int nodeID, char * userName, unsigned int addrType,
        char * ipAddress , unsigned short controlPort);

struct route_item *new_route(int netType, char * netAddr, int prefix, int hops, 
                             long bandwidth,int nbrID);

int p2p_connect(int *sock, in_addr_t srcAddr, in_addr_t destAddr, unsigned short port,int hops, int * nextNodeID);

#define TIMEOUT  5
#define MAX_HOPS 7
#define TIMER_EXCHANGE 180    /* The time interval for client exchange, keep new information with neighbors */

int addUserHops(char *userNameHops, char *userName, int hops);
int getUserHops(char *userNameHops,char *userName, unsigned char *hops);

#define  DELIMITER "&"

int methods_display();

int acl_insert4(struct access_list4 *acl_p,struct access_list_item4 * item_p);
struct access_list_item4 * new_acl4( in_addr_t netAddr, int prefix, int action);
